#ifndef __CPQUEUE_HPP__
#define __CPQUEUE_HPP__

#include"lockGuard.hpp"
#include<iostream>
#include<queue>


#define MAX_NUM 5

template<class T>
class BlockQueue {
public:
  BlockQueue(size_t capacity = MAX_NUM)
    :_capacity(capacity)
  {
    pthread_mutex_init(&_mtx, nullptr);
    pthread_cond_init(&_full, nullptr);
    pthread_cond_init(&_empty, nullptr);
  }   

  bool IsEmpty() {

    return _q.size() == 0;
  }

  bool IsFull() {

    return _q.size() == _capacity;
  }

  void PushData(const T& data) {
    LockGuard LG(&_mtx);

    while(IsFull()) {
      pthread_cond_wait(&_full, &_mtx);
    }

    _q.push(data);
    
    pthread_cond_signal(&_empty);
  }

  void PopData(T& data) {
    LockGuard LG(&_mtx);

    while(IsEmpty()) {
      pthread_cond_wait(&_empty, &_mtx);
    }

    data = _q.front();
    _q.pop();

    pthread_cond_signal(&_full);
  }
private:
  pthread_cond_t _full;
  pthread_cond_t _empty;
  pthread_mutex_t _mtx;
  std::queue<T> _q;
  size_t _capacity;
};


#endif
